// shared_ptr实现
// 多个对象共同管理一份资源 -> 需要互斥锁
// 引用计数是否会永远不等于0 ? 可能会 ->

#include <iostream>
#include <mutex>
#include <memory>

template <typename Type>
class shared_ptr
{
private:
    Type *_pointer;
    // int _count; // 普通变量可否记录管理共同资源的对象数量 ? 不行, 原因 : 每个对象都有一份, 不能代表共同拥有, 需要一个计数来管理
    // std::mutex _mutex; // 互斥锁 -> 同样互斥锁是多个对象共同拥有, 需要一个互斥锁来管理
    int *_count;
    std::mutex *_mutex;

public:
    shared_ptr(Type *pointer) : _pointer(pointer), _count(new int(1)), _mutex(new std::mutex) 
    {
        // std::cout << "constructer this :" << this << std::endl;
    }

    shared_ptr(const shared_ptr<Type> &sharedPtr) : _pointer(sharedPtr._pointer), _count(sharedPtr._count), _mutex(sharedPtr._mutex)
    {
        // std::cout << "shared_ptr(shared_ptr<Type>& sharedPtr)" << std::endl;
        addCount();
    }

    shared_ptr<Type> &operator=(shared_ptr<Type> &sharedPtr)
    {
        // std::cout << "operator=(), this :" << this << std::endl;
        if (this != &sharedPtr)
        {
            destory();
            _pointer = sharedPtr._pointer;
            _count = sharedPtr._count;
            _mutex = sharedPtr._mutex;
            addCount();
        }
        return *this;
    }

    ~shared_ptr()
    {
        destory();
    }

    Type &operator*()
    {
        return *_pointer;
    }

    Type *operator->()
    {
        return _pointer;
    }

    Type *get() const
    {
        return _pointer;
    }

    int use_count() const noexcept
    {
        return *_count;
    }

private:
    void addCount()
    {
        _mutex->lock();
        ++(*_count);
        _mutex->unlock();
    }

    void destory()
    {
        _mutex->lock();
        bool isDestory = false;
        if (--(*_count) == 0 && _pointer != nullptr)
        {
            delete _pointer;
            _pointer = nullptr;
            delete _count;
            _count = nullptr;
            isDestory = true;
            // printf("this: %p, destory!\n", this);
        }
        _mutex->unlock();
        if (isDestory)
        {
            delete _mutex;
        }
    }
};

int main()
{
    shared_ptr<int> s1(new int());
    shared_ptr<int> s2 = s1;
    shared_ptr<int> s3 = s1;
    shared_ptr<int> s4(new int());
    s1 = s4;

    // 打印
    std::cout << "s1 : " << s1.use_count() << std::endl;
    std::cout << "s2 : " << s2.use_count() << std::endl;
    std::cout << "s3 : " << s3.use_count() << std::endl;

    std::cout << "s4 : " << s4.use_count() << std::endl;

    return 0;
}
